package org.mcflier.appuntamento.io.driver.rss.torrent;

import java.io.IOException;
import java.net.MalformedURLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

import org.gnu.stealthp.rsslib.RSSChannel;
import org.gnu.stealthp.rsslib.RSSException;
import org.gnu.stealthp.rsslib.RSSHandler;
import org.gnu.stealthp.rsslib.RSSItem;
import org.gnu.stealthp.rsslib.RSSParser;
import org.mcflier.appuntamento.core.Factory;
import org.mcflier.appuntamento.core.exception.ModulesException;
import org.mcflier.appuntamento.core.logger.LoggerManager;
import org.mcflier.appuntamento.data.model.Torrent;
import org.mcflier.appuntamento.data.model.TorrentList;
import org.mcflier.appuntamento.data.model.TorrentSource;
import org.mcflier.appuntamento.i18n.I18N;
import org.mcflier.appuntamento.i18n.exception.I18NLanguageNotFoundException;
import org.mcflier.appuntamento.io.driver.rss.RssTools;
import org.mcflier.appuntamento.io.driver.rss.torrent.interfaces.IRssTorrentDriver;
import org.mcflier.appuntamento.io.exception.RSSConnectionException;
import org.mcflier.appuntamento.io.exception.RSSParsingException;

public abstract class AbstractRssTorrentDriver implements IRssTorrentDriver {
	
	public static final String TITLE_TAG = "title";
	public static final String LINK_TAG = "link";
	public static final String DESCRIPTION_TAG = "description";
	public static final String LANGUAGE_TAG = "language";
	public static final String PUBDATE_TAG = "pubDate";
	public static final String LASTBUILDDATE_TAG = "lastBuildDate";
	public static final String DOCS_TAG = "docs";
	public static final String GUID_TAG = "guid";
	public static final String GENERATOR_TAG = "generator";
	public static final String COMMENTS_TAG = "comments";
	public static final String CATEGORY_TAG = "category";
	public static final String CONTENTLENGTH_TAG = "contentLength";
	public static final String INFOHASH_TAG = "infoHash";
	public static final String MAGNETURI_TAG = "magnetURI";
	
	protected Logger logger;
	private Properties properties;
	private List<String> hdResources;
	private List<String> sdResources;
	private TorrentSource source;
	
	public AbstractRssTorrentDriver() throws ModulesException{
		this.logger = ((LoggerManager)Factory.getInstance().getModuleInstance(Factory.MODULE_LOGGER)).getLogger(this.getClass().getName());
		this.properties = null;
		
		this.hdResources = new ArrayList<String>();
		this.sdResources = new ArrayList<String>();
	}
	
	public void init(Properties properties, TorrentSource source){
		if(properties == null)
			throw new NullPointerException("Properties argument must not be null");
		
		this.properties = properties;
		this.source = source;
	}
	
	public TorrentSource getSource(){
		return this.source;
	}
	
	protected TorrentList getList(String link, Timestamp since) throws RSSConnectionException, RSSParsingException{
		RSSHandler handler = new RSSHandler();
		try {
			String filepath = RssTools.getRSSContentFile(link).getAbsolutePath();
			RSSParser.parseXmlFile(filepath, handler, false);
			RSSChannel channel = handler.getRSSChannel();
			TorrentList torrentList = new TorrentList(link, channel.getTitle(), link);
			torrentList.setDescription(channel.getDescription());
			try {
				torrentList.setLanguage(((I18N)Factory.getInstance().getModuleInstance(Factory.MODULE_I18N)).createLanguage(channel.getLanguage()));
			} catch (I18NLanguageNotFoundException e) {
				this.logger.warning("The torrent rss language was not retrieved: "+e.getMessage());
			} catch (ModulesException e) {
				this.logger.warning("Problem while retrieving the torrent rss language: "+e.getMessage());
			}
			torrentList.setPubDate(RssTools.convertToTimestamp(channel.getPubDate()));
			torrentList.setLastBuildDate(RssTools.convertToTimestamp(channel.getLastBuildDate()));

			LinkedList objects = channel.getItems();
			Timestamp pubDate;
			RSSItem item;
			Torrent torrentItem = null;

			for (Object object : objects) {
				item = (RSSItem)object;
				pubDate = RssTools.convertToTimestamp(item.getPubDate());

				if(pubDate!=null && pubDate.after(since) || pubDate.equals(since)){
					
					torrentItem = this.readTorrent(item);
					this.logger.fine("Read torrent: "+torrentItem);
					torrentList.addItem(torrentItem);
				}
			}

			return torrentList;
		} catch (MalformedURLException e) {
			throw new RSSConnectionException("Malformed rss url: "+link, e);
		}  catch (RSSException e) {
			throw new RSSParsingException("Error parsing the rss file: "+link, e);
		} catch (IOException e) {
			throw new RSSConnectionException("Error accessing url content: "+link, e);
		}
	}
	
	public abstract Torrent readTorrent(RSSItem item);
	
	@Override
	public abstract List<TorrentList> getHDTorrents() throws RSSConnectionException, RSSParsingException;

	@Override
	public abstract List<TorrentList> getHDTorrents(Timestamp since) throws RSSConnectionException, RSSParsingException;
	
	@Override
	public abstract List<TorrentList> getSDTorrents() throws RSSConnectionException, RSSParsingException;

	@Override
	public abstract List<TorrentList> getSDTorrents(Timestamp since) throws RSSConnectionException, RSSParsingException;

	@Override
	public abstract List<TorrentList> getUndefinedTorrents() throws RSSConnectionException, RSSParsingException;

	@Override
	public abstract List<TorrentList> getUndefinedTorrents(Timestamp since) throws RSSConnectionException, RSSParsingException;
}
